← Back to Frontend System Design Blogs

Checkout Module – Low Level Design

2025-06-28📖 4 min read

Share:

🛒 Step 6: Checkout Module – Low Level Design (LLD)

This document describes the low-level design and implementation details for the checkout feature module, handling address selection, payment processing, and order confirmation in the Angular e-commerce app.


📦 Module Structure

src/
├── app/
│   └── features/
│       └── checkout/
│           ├── components/
│           │   ├── address-selection/
│           │   ├── payment/
│           │   └── order-confirmation/
│           ├── services/
│           │   └── checkout.service.ts
│           ├── store/
│           │   ├── checkout.actions.ts
│           │   ├── checkout.reducer.ts
│           │   ├── checkout.effects.ts
│           │   └── checkout.selectors.ts
│           ├── models/
│           │   └── checkout.model.ts
│           ├── checkout-routing.module.ts
│           └── checkout.module.ts

🧱 Component Breakdown

🏠 AddressSelectionComponent

  • Displays saved addresses for user to select for delivery
  • Option to add/edit addresses (opens modal or navigates to AddressFormComponent)
  • Validates selected address before proceeding

💳 PaymentComponent

  • Supports multiple payment methods (credit card, PayPal, wallet)
  • Uses reactive forms with validation for card details
  • Handles payment authorization and error states

✅ OrderConfirmationComponent

  • Shows order summary, delivery address, payment method
  • Confirms order placement and displays success or failure messages
  • Option to view order details or continue shopping

🧪 Service: CheckoutService

Manages checkout-related API calls.

@Injectable({ providedIn: "root" })
export class CheckoutService {
  constructor(private http: HttpClient) {}

  getUserAddresses(): Observable<Address[]> {
    return this.http.get<Address[]>("/api/user/addresses");
  }

  processPayment(paymentInfo: PaymentInfo): Observable<PaymentResponse> {
    return this.http.post<PaymentResponse>(
      "/api/checkout/payment",
      paymentInfo
    );
  }

  placeOrder(order: OrderRequest): Observable<OrderResponse> {
    return this.http.post<OrderResponse>("/api/checkout/order", order);
  }
}

🧩 NgRx Store (optional)

✅ Actions – checkout.actions.ts

export const loadAddresses = createAction("[Checkout] Load Addresses");
export const loadAddressesSuccess = createAction(
  "[Checkout] Load Addresses Success",
  props<{ addresses: Address[] }>()
);

export const submitPayment = createAction(
  "[Checkout] Submit Payment",
  props<{ paymentInfo: PaymentInfo }>()
);
export const submitPaymentSuccess = createAction(
  "[Checkout] Submit Payment Success"
);
export const submitPaymentFailure = createAction(
  "[Checkout] Submit Payment Failure",
  props<{ error: any }>()
);

export const placeOrder = createAction(
  "[Checkout] Place Order",
  props<{ orderRequest: OrderRequest }>()
);
export const placeOrderSuccess = createAction(
  "[Checkout] Place Order Success",
  props<{ orderResponse: OrderResponse }>()
);
export const placeOrderFailure = createAction(
  "[Checkout] Place Order Failure",
  props<{ error: any }>()
);

🔁 Reducer – checkout.reducer.ts

Manages state slices for addresses, payment status, order confirmation, loading flags, and error messages.


🌐 Effects – checkout.effects.ts

Handles side effects such as fetching addresses, processing payments, and placing orders asynchronously.


🔍 Selectors – checkout.selectors.ts

export const selectAddresses = createSelector(
  selectCheckoutState,
  (state) => state.addresses
);
export const selectPaymentStatus = createSelector(
  selectCheckoutState,
  (state) => state.paymentStatus
);
export const selectOrderConfirmation = createSelector(
  selectCheckoutState,
  (state) => state.orderConfirmation
);

🔄 API Contracts

Endpoint Method Request Body Response
/user/addresses GET Address[]
/checkout/payment POST PaymentInfo PaymentResponse
/checkout/order POST OrderRequest OrderResponse

📐 Models

export interface PaymentInfo {
  method: string;
  cardNumber?: string;
  expiryDate?: string;
  cvv?: string;
  paypalId?: string;
  walletId?: string;
}

export interface PaymentResponse {
  success: boolean;
  transactionId?: string;
  errorMessage?: string;
}

export interface OrderRequest {
  cartId: string;
  addressId: string;
  paymentTransactionId: string;
}

export interface OrderResponse {
  orderId: string;
  status: string;
  estimatedDelivery: string;
}

🚦 Routing & Guards

const routes: Routes = [
  {
    path: "address-selection",
    component: AddressSelectionComponent,
    canActivate: [AuthGuard],
  },
  { path: "payment", component: PaymentComponent, canActivate: [AuthGuard] },
  {
    path: "order-confirmation",
    component: OrderConfirmationComponent,
    canActivate: [AuthGuard],
  },
];

🔐 Security & UX

  • Use AuthGuard for all checkout routes
  • Validate forms thoroughly (address, payment)
  • Show loaders during API calls and error/success feedback
  • Prevent multiple submissions of payment/order requests

✅ Responsibilities Summary

Part Responsibility
AddressSelectionComponent Select or add delivery address
PaymentComponent Process payment through supported methods
OrderConfirmationComponent Confirm and display order details
CheckoutService API communication for checkout flow